package cn.jilian.entity.support;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.persistence.PostRemove;
import javax.persistence.PrePersist;
import javax.persistence.Table;

import org.apache.commons.lang3.StringUtils;
import org.springframework.jdbc.core.JdbcTemplate;

import cn.jilian.common.config.SpringBeans;
import cn.jilian.entity.AbstractEntity;



public class BaseEntitySeqListener {

	private  JdbcTemplate jdbcTemplate;
	
	private Map<Class<? extends AbstractEntity>,String> pojoSqlMap;
	
	private Map<Class<? extends AbstractEntity>,String> entityTableMap;
	
	private Map<Class<? extends AbstractEntity>,String> offSetSeqSqlMap;
	
	public BaseEntitySeqListener() {
		entityTableMap=new ConcurrentHashMap<>();
		pojoSqlMap=new ConcurrentHashMap<>();
		this.offSetSeqSqlMap=new ConcurrentHashMap<>();
	}
	
	private Table getTableAnno(Class<?> type) {
		Table t=type.getAnnotation(Table.class);
		if(t!=null)return t;
		type=type.getSuperclass();
		if(type!=null) {
			return getTableAnno(type);
		}else {
			return null;
		}
	}
	private String getTable(Class<? extends AbstractEntity> clazz) {
		String table=entityTableMap.get(clazz);
		if(table==null) {
			synchronized (this) {
				Table t=getTableAnno(clazz);
				if(t!=null) {
					table= t.name();
					
				}else {
					table="";
				}
				entityTableMap.put(clazz, table);
			}
			
		}
		return table;
	}
	
	private String getUpdateSeqSql(AbstractEntity baseEntity) {
		Class<? extends AbstractEntity> clazz=baseEntity.getClass();
		String sql=offSetSeqSqlMap.get(clazz);
		if(sql==null) {
			synchronized (this) {
				String table=getTable(clazz);
				if(StringUtils.isBlank(table)) {
					sql="";
				}else {
					sql=new StringBuilder("update ")
							.append(table)
							.append(" set seq=seq-1 where fid=? and rank=? and seq>?").toString();
				}
				
				offSetSeqSqlMap.put(clazz, sql);
			}
			
		}
		return sql;
	}
	
	private String getSql(AbstractEntity baseEntity) {
		
		Class<? extends AbstractEntity> clazz=baseEntity.getClass();
		String sql=pojoSqlMap.get(clazz);
		if(sql==null) {
			synchronized (this) {
				String table=getTable(clazz);
				if(StringUtils.isBlank(table)) {
					sql="";
				}else {
					sql=new StringBuilder("select max(seq) as max from ")
							.append(table)
							.append(" where fid=? and rank=?").toString();
				}
				
				pojoSqlMap.put(clazz, sql);
			}
			
		}
		return sql;
	}
	@PrePersist
    public void initEntity(AbstractEntity baseEntity){
		
		String sql=getSql(baseEntity);
		if(StringUtils.isNotBlank(sql)) {
			Integer seq=baseEntity.getSeq();
			if(seq==null) {
				Long fid=baseEntity.getFid();
				Integer rank=baseEntity.getRank();
				if(fid!=null&&rank!=null) {
					if(this.jdbcTemplate==null) {
						this.jdbcTemplate=SpringBeans.getBean(JdbcTemplate.class);
					}
					try {
					Integer max=jdbcTemplate.queryForObject(sql, new Object[] {fid,rank},Integer.class);
					max=(max==null)?1:max+1;
					baseEntity.setSeq(max);
					}catch(Exception e) {
						e.printStackTrace();
						baseEntity.setSeq(1);
					}
				}
			}
		}
		
    }
    /**
     * 删除后
     */
	@PostRemove
    public void postDeleteEntity(AbstractEntity baseEntity){
       String offsetSql=getUpdateSeqSql(baseEntity);
       if(StringUtils.isNotBlank(offsetSql)) {
    	  Long fid= baseEntity.getFid();
    	  Integer seq=baseEntity.getSeq();
    	  Integer rank=baseEntity.getRank();
    	  if(fid!=null&&seq!=null&&rank!=null) {
    		  if(jdbcTemplate==null) {
    			  jdbcTemplate=SpringBeans.getBean(JdbcTemplate.class);
    		  }
    		  jdbcTemplate.update(offsetSql,fid,rank,seq);
    	  }
       }
    }
}
